home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr42 / vocshow2.zip / PC_SOUND.ASM < prev    next >
Assembly Source File  |  1993-06-08  |  6KB  |  231 lines

  1. -- Copyright 1992 by Tom Moran.  May be used by anyone for any purpose.
  2.  
  3. package assembly pc_sound is
  4.  
  5. if memory_model = 0 then
  6.   pragma memory_model(0);
  7. else
  8.   pragma memory_model(1);
  9. end if;
  10.  
  11. CSEG
  12.         jmp     init                    -- jump to initialization
  13.  
  14. DSEG
  15. prevwhistle db ?
  16. a_sample_duration dw ?
  17. on_off_bytes db 256 dup(?)
  18. doubling db ?
  19.  
  20. CSEG
  21. on_off_pattern equ  $
  22.  dw 2#00000000_11111111#       -- 0    nibbles are in sign+magnitude form
  23.  dw 2#00000001_11111111#       -- 1
  24.  dw 2#00000011_11111111#       -- 2
  25.  dw 2#00000111_11111111#       -- 3
  26.  dw 2#00001111_11111111#       -- 4
  27.  dw 2#00011111_11111111#       -- 5
  28.  dw 2#00111111_11111111#       -- 6
  29.  dw 2#01111111_11111111#       -- 7
  30.  dw 2#00000000_11111110#       -- -1
  31.  dw 2#00000000_01111110#       -- -2
  32.  dw 2#00000000_00111110#       -- -3
  33.  dw 2#00000000_00011110#       -- -4
  34.  dw 2#00000000_00001110#       -- -5
  35.  dw 2#00000000_00000110#       -- -6
  36.  dw 2#00000000_00000010#       -- -7
  37.  dw 2#00000000_00000000#       -- -8
  38.  
  39. get_ticks:             -- return current tick count in ax
  40.        xor al,al
  41.        pushf           --  save int enable status
  42.        cli             --  lock out interrupts
  43.        out 43h,al      --  read counter 0
  44.        jmp short gtl   --    (don't go too fast)
  45. gtl:
  46.        in al,40h       --  get lsb of timer
  47.        xchg ah,al      --
  48.        jmp short gth   --    (don't go too fast)
  49. gth:
  50.        in al,40h       --  get msb of timer
  51.        xchg ah,al      --
  52.        popf            --  restore int enable status
  53.        ret
  54.  
  55. play_ax_till_dx:       -- destroys ax,bx
  56.                        -- high nibble of al contains amplitude
  57.                        -- dx contains timeout value
  58. --  if al & 70 = 0 doubling=false
  59. --  if doubling, al |= 40
  60. --  else if al & 70 > 40 then doubling=true
  61.        mov bl,al
  62.        and bl,16#70#
  63.        jnz if_d
  64.        mov [doubling],bl
  65.        jmp short fini_doubling
  66. if_d:
  67.        test [doubling],1
  68.        jz e_d
  69.        or al,16#40#
  70.        jmp short fini_doubling
  71. e_d:
  72.        cmp bl,16#40#
  73.        jle fini_doubling
  74.        mov [doubling],1
  75. fini_doubling:
  76.  
  77.        mov bx,on_off_bytes
  78.        add bx,ax
  79.        xchg si,bx
  80.        even
  81. pbd_loop:              -- output 16 speaker on/off bytes, then,
  82.        push dx         -- if we haven't timed out, do it again
  83.        mov dx,61h
  84.        lodsw
  85.        out dx,al
  86.        mov al,ah
  87.        out dx,al
  88.        lodsw
  89.        out dx,al
  90.        mov al,ah
  91.        out dx,al
  92.        lodsw
  93.        out dx,al
  94.        mov al,ah
  95.        out dx,al
  96.        lodsw
  97.        out dx,al
  98.        mov al,ah
  99.        out dx,al
  100.        lodsw
  101.        out dx,al
  102.        mov al,ah
  103.        out dx,al
  104.        lodsw
  105.        out dx,al
  106.        mov al,ah
  107.        out dx,al
  108.        lodsw
  109.        out dx,al
  110.        mov al,ah
  111.        out dx,al
  112.        lodsw
  113.        out dx,al
  114.        xor al,al
  115.        pushf           --  save int enable status
  116.        cli             --  lock out interrupts
  117.        out 43h,al      --  read counter 0
  118.        mov al,ah
  119.        out dx,al
  120.        in al,40h       --  get lsb of timer
  121.        xchg ah,al      --
  122.        sub si,16
  123.        in al,40h       --  get msb of timer
  124.        xchg ah,al      --
  125.        popf            --  restore int enable status
  126.        pop dx
  127.        cmp ax,dx
  128.        jns pbd_loop
  129.        xchg si,bx
  130.        ret
  131.  
  132. play_it_out:
  133.                        -- ds:si => sound block
  134.                        -- cx    => N of bytes in sound block
  135.                        -- destroys ax,bx,dx and si,cx
  136.        mov [doubling],0
  137.        call get_ticks
  138.        mov dx,ax
  139.        cld
  140. play_it_out_loop:
  141.        mov al,es:[si]
  142.        and ax,16#00F0#;
  143.        sub dx,[a_sample_duration]
  144.        call play_ax_till_dx
  145.        mov al,es:[si]
  146.        inc si
  147.        and ax,16#000F#
  148.        shl al,1
  149.        shl al,1
  150.        shl al,1
  151.        shl al,1
  152.        sub dx,[a_sample_duration]
  153.        call play_ax_till_dx
  154.        loop play_it_out_loop
  155.        mov al,[prevwhistle]
  156.        out 61h,al
  157.        ret
  158.  
  159. procedure set_sample_rate(samples_per_second:in sample_rates) is
  160.        pop ax          -- save ret address
  161.        if memory_model = 1 then
  162.          pop dx
  163.        end if;
  164.        pop cx          -- cx:=sound_length
  165.        if memory_model = 1 then  -- restore ret address
  166.          push dx
  167.        end if;
  168.        push ax
  169.        mov ax,13532    -- dx:ax := 1193180
  170.        mov dx,18
  171.        div cx
  172.        mov [a_sample_duration],ax
  173.        if memory_model = 0 then
  174.          ret
  175.        else
  176.          ret far
  177.        end if;
  178. end set_sample_rate;
  179.  
  180. procedure playback(sound:in system.address;sound_length:in natural) is
  181.                        -- clobbers ax,bx,cx,dx,si
  182.        pop ax          -- save ret address
  183.        if memory_model = 1 then
  184.          pop dx
  185.        end if;
  186.        pop cx          -- cx:=sound_length
  187.        pop si          -- si:=sound(sound'first)'address
  188.        mov bx,es
  189.        les si,lword ptr[si]
  190.        if memory_model = 1 then  -- restore ret address
  191.          push dx
  192.        end if;
  193.        push ax
  194.        push bx
  195.        call play_it_out
  196.        pop  es
  197.        if memory_model = 0 then
  198.          ret
  199.        else
  200.          ret far
  201.        end if;
  202. end playback;
  203.  
  204. init:
  205.        mov ax,149      -- default sample rate:=8K
  206.        mov [a_sample_duration],ax
  207.        in al,61h
  208.        mov [prevwhistle],al
  209.        and al,16#FD#
  210.        mov bl,al               -- fill on_off_bytes with 16 lists of 16
  211.        mov di,on_off_bytes     -- speaker control bytes, on and off matching
  212.        mov cx,16               -- the bits in on_off_pattern
  213.        cld
  214.        mov si,on_off_pattern
  215. amplitude_loop:
  216.        push cx
  217.        seg cs
  218.        lodsw
  219.        mov cx,16
  220. bit_loop:
  221.        mov bh,2        --      bh:=non_speaker_bits | one bit from ax
  222.        and bh,al
  223.        or  bh,bl
  224.        mov [di],bh
  225.        inc di
  226.        ror ax,1
  227.        loop bit_loop
  228.        pop cx
  229.        loop amplitude_loop
  230. end pc_sound;
  231.